ποΈGitΠ―ΡΠ°ποΈ
Commit 89fe2b58d7aa6f0af30af91e2ccf72f365c80bc7
Parents : 19d10a1
Author : James Rich <2199651+jamesarich@users.noreply.github.com>
Signature : Signature validation error
Date : 2026-05-20T08:42:34-07:00
Committer : GitHub <noreply@github.com>
Date : 2026-05-20T10:42:34-05:00
docs(nav): fix sidebar nesting, dynamic language switcher, and delete translations page (#5535)
Changes
31 files changed, 223 insertions(+), 204 deletions(-)
Diff
diff --git a/.agent_memory/session_context.md b/.agent_memory/session_context.md
index 98f32aab60..13e5cfcfcc 100644
--- a/.agent_memory/session_context.md
+++ b/.agent_memory/session_context.md
@@ -3,6 +3,25 @@
# Do NOT edit or remove previous entries β stale state claims cause agent confusion.
# Format: ## YYYY-MM-DD β <summary>
+## 2026-05-20 β Replaced standalone translations landing page with dynamic global header language switcher dropdown
+- Deleted redundant standalone page `docs/en/translations.md` and updated `docs/README.md` to reflect layout change.
+- Completely re-engineered `docs/_includes/language_switcher.html` to:
+ 1. Dynamically parse active page paths and locales, matching default English pages with translated variants.
+ 2. Bind button text to native active language names (e.g., displaying "ΠΠ΅Π»Π°ΡΡΡΠΊΠ°Ρ" instead of hardcoded "English").
+ 3. Pre-verify file existence in `site.pages` to only render valid translation links, preventing any 404 errors.
+ 4. Automatically hide the language switcher on English pages that do not have translations available yet.
+- Modified custom CSS styles in `docs/_includes/head_custom.html` to use `right: 0; left: auto;` layout alignment, preventing dropdown menu overflows on smaller screens.
+- Successfully built and verified live documentation pages in the browser using the browser subagent, confirming fully operational dynamic swappers.
+- Ran quality and validation checks: `./gradlew generateDocsBundle validateDocsBundle spotlessCheck detekt` (100% SUCCESSFUL).
+
+## 2026-05-20 β Fixed Jekyll documentation site left navigation nesting and sub-page visibility
+- Cleaned up redundant and brittle dynamic default scope parent settings in `docs/_config.yml`.
+- Added explicit `parent: User Guide` front-matter fields to all 17 English user guide markdown files under `docs/en/user/`.
+- Added explicit `parent: Developer Guide` front-matter fields to all 9 English developer guide markdown files under `docs/en/developer/`.
+- Run and verified Gradle documentation bundle compilation: `./gradlew generateDocsBundle validateDocsBundle` (PASSED: 672 pages).
+- Validated formatting and static analysis rules: `./gradlew spotlessApply spotlessCheck detekt` (100% green).
+- Successfully completed full baseline compilation checks with `./gradlew assembleDebug`.
+
## 2026-05-20 β Completely overhauled, simplified, and pushed Flatpak offline source automation
- Completely retired the third-party `flatpak-gradle-generator` plugin and its associated complex configuration and library overrides (removed ~150 lines of boilerplate).
- Implemented a native JVM-based custom Gradle task `GenerateFlatpakSourcesTask` inside `gradle/flatpak.gradle.kts` which walks the post-compilation Gradle cache and generates a perfectly sorted, deduplicated `flatpak-sources.json` in under 3 seconds.
diff --git a/docs/README.md b/docs/README.md
index 35461fd8d8..7db6d42bfc 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -17,8 +17,7 @@ docs/
β βββ developer/ β Developer Guide pages
β βββ index.md β Site home page
β βββ user.md β User Guide nav parent
-β βββ developer.md β Developer Guide nav parent
-β βββ translations.md β Translations landing page
+β βββ developer.md β Developer Guide nav parent
βββ fr-rFR/ β French (Crowdin-generated)
β βββ user/ β Translated user guide
βββ de-rDE/ β German (Crowdin-generated)
diff --git a/docs/_config.yml b/docs/_config.yml
index d29e8509e4..39ddd8b25e 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -30,171 +30,169 @@ defaults:
- scope:
path: "en/user/"
values:
- parent: User Guide
layout: default
- scope:
path: "en/developer/"
values:
- parent: Developer Guide
layout: default
# Locale-translated pages are excluded from main nav but still rendered.
# They use a dedicated locale layout with a back-link to the English version.
# Auto-generated from Android app locales (values-* resource dirs).
- scope:
- path: "ar"
+ path: "ar-rSA"
values:
layout: locale_page
- locale: ar
+ locale: ar-rSA
nav_exclude: true
- scope:
- path: "be"
+ path: "be-rBY"
values:
layout: locale_page
- locale: be
+ locale: be-rBY
nav_exclude: true
- scope:
- path: "bg"
+ path: "bg-rBG"
values:
layout: locale_page
- locale: bg
+ locale: bg-rBG
nav_exclude: true
- scope:
- path: "ca"
+ path: "ca-rES"
values:
layout: locale_page
- locale: ca
+ locale: ca-rES
nav_exclude: true
- scope:
- path: "cs"
+ path: "cs-rCZ"
values:
layout: locale_page
- locale: cs
+ locale: cs-rCZ
nav_exclude: true
- scope:
- path: "de"
+ path: "de-rDE"
values:
layout: locale_page
- locale: de
+ locale: de-rDE
nav_exclude: true
- scope:
- path: "el"
+ path: "el-rGR"
values:
layout: locale_page
- locale: el
+ locale: el-rGR
nav_exclude: true
- scope:
- path: "es"
+ path: "es-rES"
values:
layout: locale_page
- locale: es
+ locale: es-rES
nav_exclude: true
- scope:
- path: "et"
+ path: "et-rEE"
values:
layout: locale_page
- locale: et
+ locale: et-rEE
nav_exclude: true
- scope:
- path: "fi"
+ path: "fi-rFI"
values:
layout: locale_page
- locale: fi
+ locale: fi-rFI
nav_exclude: true
- scope:
- path: "fr"
+ path: "fr-rFR"
values:
layout: locale_page
- locale: fr
+ locale: fr-rFR
nav_exclude: true
- scope:
- path: "ga"
+ path: "ga-rIE"
values:
layout: locale_page
- locale: ga
+ locale: ga-rIE
nav_exclude: true
- scope:
- path: "gl"
+ path: "gl-rES"
values:
layout: locale_page
- locale: gl
+ locale: gl-rES
nav_exclude: true
- scope:
- path: "he"
+ path: "iw-rIL"
values:
layout: locale_page
- locale: he
+ locale: iw-rIL
nav_exclude: true
- scope:
- path: "hr"
+ path: "hr-rHR"
values:
layout: locale_page
- locale: hr
+ locale: hr-rHR
nav_exclude: true
- scope:
- path: "ht"
+ path: "ht-rHT"
values:
layout: locale_page
- locale: ht
+ locale: ht-rHT
nav_exclude: true
- scope:
- path: "hu"
+ path: "hu-rHU"
values:
layout: locale_page
- locale: hu
+ locale: hu-rHU
nav_exclude: true
- scope:
- path: "is"
+ path: "is-rIS"
values:
layout: locale_page
- locale: is
+ locale: is-rIS
nav_exclude: true
- scope:
- path: "it"
+ path: "it-rIT"
values:
layout: locale_page
- locale: it
+ locale: it-rIT
nav_exclude: true
- scope:
- path: "ja"
+ path: "ja-rJP"
values:
layout: locale_page
- locale: ja
+ locale: ja-rJP
nav_exclude: true
- scope:
- path: "ko"
+ path: "ko-rKR"
values:
layout: locale_page
- locale: ko
+ locale: ko-rKR
nav_exclude: true
- scope:
- path: "lt"
+ path: "lt-rLT"
values:
layout: locale_page
- locale: lt
+ locale: lt-rLT
nav_exclude: true
- scope:
- path: "nl"
+ path: "nl-rNL"
values:
layout: locale_page
- locale: nl
+ locale: nl-rNL
nav_exclude: true
- scope:
- path: "no"
+ path: "no-rNO"
values:
layout: locale_page
- locale: no
+ locale: no-rNO
nav_exclude: true
- scope:
- path: "pl"
+ path: "pl-rPL"
values:
layout: locale_page
- locale: pl
+ locale: pl-rPL
nav_exclude: true
- scope:
- path: "pt"
+ path: "pt-rPT"
values:
layout: locale_page
- locale: pt
+ locale: pt-rPT
nav_exclude: true
- scope:
path: "pt-rBR"
@@ -203,58 +201,64 @@ defaults:
locale: pt-rBR
nav_exclude: true
- scope:
- path: "ro"
+ path: "ro-rRO"
values:
layout: locale_page
- locale: ro
+ locale: ro-rRO
nav_exclude: true
- scope:
- path: "ru"
+ path: "ru-rRU"
values:
layout: locale_page
- locale: ru
+ locale: ru-rRU
nav_exclude: true
- scope:
- path: "sk"
+ path: "sk-rSK"
values:
layout: locale_page
- locale: sk
+ locale: sk-rSK
nav_exclude: true
- scope:
- path: "sl"
+ path: "sl-rSI"
values:
layout: locale_page
- locale: sl
+ locale: sl-rSI
nav_exclude: true
- scope:
- path: "sq"
+ path: "sq-rAL"
values:
layout: locale_page
- locale: sq
+ locale: sq-rAL
nav_exclude: true
- scope:
- path: "sr"
+ path: "sr-rLatn"
values:
layout: locale_page
- locale: sr
+ locale: sr-rLatn
nav_exclude: true
- scope:
- path: "sv"
+ path: "srp"
values:
layout: locale_page
- locale: sv
+ locale: srp
nav_exclude: true
- scope:
- path: "tr"
+ path: "sv-rSE"
values:
layout: locale_page
- locale: tr
+ locale: sv-rSE
nav_exclude: true
- scope:
- path: "uk"
+ path: "tr-rTR"
values:
layout: locale_page
- locale: uk
+ locale: tr-rTR
+ nav_exclude: true
+ - scope:
+ path: "uk-rUA"
+ values:
+ layout: locale_page
+ locale: uk-rUA
nav_exclude: true
- scope:
path: "zh-rCN"
diff --git a/docs/_data/locales.yml b/docs/_data/locales.yml
index a40998a1c8..e0f94ef44d 100644
--- a/docs/_data/locales.yml
+++ b/docs/_data/locales.yml
@@ -1,114 +1,117 @@
# Supported documentation locales.
-# Each entry maps a Crowdin 2-letter code to its native name.
+# Each entry maps a regional qualifier code to its native name.
# Pages land at docs/{code}/user/*.md via Crowdin sync.
# Synced with Android app locales (values-* resource dirs).
-ar:
+ar-rSA:
name: "Ψ§ΩΨΉΨ±Ψ¨ΩΨ©"
dir: rtl
-be:
+be-rBY:
name: "ΠΠ΅Π»Π°ΡΡΡΠΊΠ°Ρ"
dir: ltr
-bg:
+bg-rBG:
name: "ΠΡΠ»Π³Π°ΡΡΠΊΠΈ"
dir: ltr
-ca:
+ca-rES:
name: "CatalΓ "
dir: ltr
-cs:
+cs-rCZ:
name: "ΔeΕ‘tina"
dir: ltr
-de:
+de-rDE:
name: "Deutsch"
dir: ltr
-el:
+el-rGR:
name: "Ξλληνικά"
dir: ltr
-es:
+es-rES:
name: "EspaΓ±ol"
dir: ltr
-et:
+et-rEE:
name: "Eesti"
dir: ltr
-fi:
+fi-rFI:
name: "Suomi"
dir: ltr
-fr:
+fr-rFR:
name: "FranΓ§ais"
dir: ltr
-ga:
+ga-rIE:
name: "Gaeilge"
dir: ltr
-gl:
+gl-rES:
name: "Galego"
dir: ltr
-he:
+iw-rIL:
name: "Χ’ΧΧ¨ΧΧͺ"
dir: rtl
-hr:
+hr-rHR:
name: "Hrvatski"
dir: ltr
-ht:
+ht-rHT:
name: "KreyΓ²l Ayisyen"
dir: ltr
-hu:
+hu-rHU:
name: "Magyar"
dir: ltr
-is:
+is-rIS:
name: "Γslenska"
dir: ltr
-it:
+it-rIT:
name: "Italiano"
dir: ltr
-ja:
+ja-rJP:
name: "ζ₯ζ¬θͺ"
dir: ltr
-ko:
+ko-rKR:
name: "νκ΅μ΄"
dir: ltr
-lt:
+lt-rLT:
name: "LietuviΕ³"
dir: ltr
-nl:
+nl-rNL:
name: "Nederlands"
dir: ltr
-"no":
+no-rNO:
name: "Norsk"
dir: ltr
-pl:
+pl-rPL:
name: "Polski"
dir: ltr
-pt:
- name: "PortuguΓͺs"
- dir: ltr
pt-rBR:
name: "PortuguΓͺs (Brasil)"
dir: ltr
-ro:
+pt-rPT:
+ name: "PortuguΓͺs"
+ dir: ltr
+ro-rRO:
name: "RomΓ’nΔ"
dir: ltr
-ru:
+ru-rRU:
name: "Π ΡΡΡΠΊΠΈΠΉ"
dir: ltr
-sk:
+sk-rSK:
name: "SlovenΔina"
dir: ltr
-sl:
+sl-rSI:
name: "SlovenΕ‘Δina"
dir: ltr
-sq:
+sq-rAL:
name: "Shqip"
dir: ltr
-sr:
- name: "Π‘ΡΠΏΡΠΊΠΈ"
+sr-rLatn:
+ name: "Π‘ΡΠΏΡΠΊΠΈ (Latinica)"
+ dir: ltr
+srp:
+ name: "Π‘ΡΠΏΡΠΊΠΈ (ΠΠΈΡΠΈΠ»ΠΈΡΠ°)"
dir: ltr
-sv:
+sv-rSE:
name: "Svenska"
dir: ltr
-tr:
+tr-rTR:
name: "TΓΌrkΓ§e"
dir: ltr
-uk:
+uk-rUA:
name: "Π£ΠΊΡΠ°ΡΠ½ΡΡΠΊΠ°"
dir: ltr
zh-rCN:
diff --git a/docs/_includes/head_custom.html b/docs/_includes/head_custom.html
index fe012543d9..f291d4d171 100644
--- a/docs/_includes/head_custom.html
+++ b/docs/_includes/head_custom.html
@@ -125,7 +125,8 @@
.language-switcher-list {
position: absolute;
top: 100%;
- left: 0;
+ right: 0;
+ left: auto;
z-index: 100;
list-style: none;
padding: 8px 0;
diff --git a/docs/_includes/language_switcher.html b/docs/_includes/language_switcher.html
index 3fe3bb662d..11497a5d3e 100644
--- a/docs/_includes/language_switcher.html
+++ b/docs/_includes/language_switcher.html
@@ -6,49 +6,49 @@
Usage: {% include language_switcher.html %}
Logic:
- - Derives the current page's relative path within its section
- - Checks if translated versions exist in locale subdirectories
- - Shows a globe icon with available locale links
+ - Dynamically detects the current language and page name.
+ - Dynamically updates the switcher button's native language name.
+ - Correctly matches English pages to translated equivalents and vice versa.
+ - Pre-verifies existing files to only render valid, non-404 options.
{% endcomment %}
{% assign current_path = page.path %}
{% assign locales = site.data.locales %}
{% if locales and current_path %}
-{% assign path_parts = current_path | split: "/" %}
-{% assign first_segment = path_parts[0] %}
+ {% assign path_parts = current_path | split: "/" %}
+ {% assign first_segment = path_parts[0] %}
-{% comment %} Build the list of available translations first {% endcomment %}
-{% assign has_translations = false %}
+ {% comment %}
+ Identify the current page's language code and native language name.
+ If the first segment is defined in locales.yml, we are on a translation.
+ Otherwise, we are in default English.
+ {% endcomment %}
+ {% if locales[first_segment] %}
+ {% assign current_lang_code = first_segment %}
+ {% assign current_lang_name = locales[first_segment].name %}
+ {% else %}
+ {% assign current_lang_code = "en" %}
+ {% assign current_lang_name = "English" %}
+ {% endif %}
-{% if locales[first_segment] %}
- {% comment %} We're on a translated page β English link is always available {% endcomment %}
- {% assign has_translations = true %}
+ {% comment %}
+ Extract the relative base path (independent of locale prefix and file extension).
+ E.g., "en/user/connections.md" and "be-rBY/user/connections.md" both resolve to "user/connections".
+ {% endcomment %}
{% assign remaining_parts = path_parts | slice: 1, path_parts.size %}
- {% assign en_path = remaining_parts | join: "/" | replace: ".md", "" %}
-{% else %}
- {% comment %} Check if any translated version exists {% endcomment %}
- {% assign en_relative = current_path | replace: ".md", "" %}
- {% for locale in locales %}
- {% assign locale_code = locale[0] %}
- {% assign locale_file = locale_code | append: "/" | append: en_relative | append: ".md" %}
- {% for p in site.pages %}
- {% if p.path == locale_file %}
- {% assign has_translations = true %}
- {% break %}
- {% endif %}
- {% endfor %}
- {% if has_translations %}{% break %}{% endif %}
- {% endfor %}
-{% endif %}
+ {% assign base_path = remaining_parts | join: "/" | replace: ".md", "" %}
-{% if has_translations %}
-<details class="language-switcher" aria-label="Language options">
- <summary class="language-switcher-btn" title="View in another language">
- π <span class="lang-current">English</span>
- </summary>
- <ul class="language-switcher-list">
- {% if locales[first_segment] %}
+ {% comment %}
+ Pre-render the dropdown list items.
+ {% endcomment %}
+ {% capture dropdown_items %}
+ {% if current_lang_code != "en" %}
+ {% if base_path == "index" %}
+ {% assign en_path = "en/" %}
+ {% else %}
+ {% assign en_path = "en/" | append: base_path %}
+ {% endif %}
<li><a href="{{ en_path | relative_url }}" lang="en">English</a></li>
{% endif %}
@@ -56,16 +56,12 @@
{% assign locale_code = locale[0] %}
{% assign locale_info = locale[1] %}
- {% if locales[first_segment] %}
- {% if locale_code == first_segment %}
- {% continue %}
- {% endif %}
- {% assign locale_path = locale_code | append: "/" | append: en_path %}
- {% else %}
- {% assign locale_path = locale_code | append: "/" | append: en_relative %}
+ {% if locale_code == current_lang_code %}
+ {% continue %}
{% endif %}
- {% assign locale_file = locale_path | append: ".md" %}
+ {% assign locale_file = locale_code | append: "/" | append: base_path | append: ".md" %}
+
{% assign page_exists = false %}
{% for p in site.pages %}
{% if p.path == locale_file %}
@@ -75,10 +71,29 @@
{% endfor %}
{% if page_exists %}
+ {% if base_path == "index" %}
+ {% assign locale_path = locale_code | append: "/" %}
+ {% else %}
+ {% assign locale_path = locale_code | append: "/" | append: base_path %}
+ {% endif %}
<li><a href="{{ locale_path | relative_url }}" lang="{{ locale_code }}" {% if locale_info.dir == "rtl" %}dir="rtl"{% endif %}>{{ locale_info.name }}</a></li>
{% endif %}
{% endfor %}
- </ul>
-</details>
-{% endif %}
+ {% endcapture %}
+
+ {% assign dropdown_items_stripped = dropdown_items | strip %}
+
+ {% comment %}
+ Only render the switcher if there is at least one other language option available.
+ {% endcomment %}
+ {% if dropdown_items_stripped != "" %}
+ <details class="language-switcher" aria-label="Language options">
+ <summary class="language-switcher-btn" title="View in another language">
+ π <span class="lang-current">{{ current_lang_name }}</span>
+ </summary>
+ <ul class="language-switcher-list">
+ {{ dropdown_items }}
+ </ul>
+ </details>
+ {% endif %}
{% endif %}
diff --git a/docs/en/developer/adding-a-feature-module.md b/docs/en/developer/adding-a-feature-module.md
index ae290dbda2..acc76a9776 100644
--- a/docs/en/developer/adding-a-feature-module.md
+++ b/docs/en/developer/adding-a-feature-module.md
@@ -1,5 +1,6 @@
---
title: Adding a Feature Module
+parent: Developer Guide
nav_order: 3
last_updated: 2026-05-13
aliases:
diff --git a/docs/en/developer/architecture.md b/docs/en/developer/architecture.md
index 8d1bacc1b3..75476e1f36 100644
--- a/docs/en/developer/architecture.md
+++ b/docs/en/developer/architecture.md
@@ -1,5 +1,6 @@
---
title: Architecture
+parent: Developer Guide
nav_order: 1
last_updated: 2026-05-13
aliases:
diff --git a/docs/en/developer/codebase.md b/docs/en/developer/codebase.md
index 9f67c6e97a..10733979fc 100644
--- a/docs/en/developer/codebase.md
+++ b/docs/en/developer/codebase.md
@@ -1,5 +1,6 @@
---
title: Codebase
+parent: Developer Guide
nav_order: 2
last_updated: 2026-05-13
aliases:
diff --git a/docs/en/developer/contributing.md b/docs/en/developer/contributing.md
index f5d0bbaf65..34592d9f43 100644
--- a/docs/en/developer/contributing.md
+++ b/docs/en/developer/contributing.md
@@ -1,5 +1,6 @@
---
title: Contributing
+parent: Developer Guide
nav_order: 8
last_updated: 2026-05-13
aliases:
diff --git a/docs/en/developer/measurement.md b/docs/en/developer/measurement.md
index 83eceac3af..07480cffa8 100644
--- a/docs/en/developer/measurement.md
+++ b/docs/en/developer/measurement.md
@@ -1,5 +1,6 @@
---
title: Measurement & Formatting
+parent: Developer Guide
nav_order: 9
last_updated: 2026-05-13
aliases:
diff --git a/docs/en/developer/navigation-and-deep-links.md b/docs/en/developer/navigation-and-deep-links.md
index c86afdf852..45bc5e6b12 100644
--- a/docs/en/developer/navigation-and-deep-links.md
+++ b/docs/en/developer/navigation-and-deep-links.md
@@ -1,5 +1,6 @@
---
title: Navigation & Deep Links
+parent: Developer Guide
nav_order: 4
last_updated: 2026-05-13
aliases:
diff --git a/docs/en/developer/persistence.md b/docs/en/developer/persistence.md
index 4f1f1f472f..1d9467e157 100644
--- a/docs/en/developer/persistence.md
+++ b/docs/en/developer/persistence.md
@@ -1,5 +1,6 @@
---
title: Persistence
+parent: Developer Guide
nav_order: 6
last_updated: 2026-05-13
aliases:
diff --git a/docs/en/developer/testing.md b/docs/en/developer/testing.md
index d1ed344fc5..3706a14f39 100644
--- a/docs/en/developer/testing.md
+++ b/docs/en/developer/testing.md
@@ -1,5 +1,6 @@
---
title: Testing
+parent: Developer Guide
nav_order: 7
last_updated: 2026-05-13
aliases:
diff --git a/docs/en/developer/transport.md b/docs/en/developer/transport.md
index 82faaa2699..f62616f93a 100644
--- a/docs/en/developer/transport.md
+++ b/docs/en/developer/transport.md
@@ -1,5 +1,6 @@
---
title: Transport
+parent: Developer Guide
nav_order: 5
last_updated: 2026-05-13
aliases:
diff --git a/docs/en/translations.md b/docs/en/translations.md
deleted file mode 100644
index feda7aaa59..0000000000
--- a/docs/en/translations.md
+++ /dev/null
@@ -1,46 +0,0 @@
----
-title: Translations
-layout: default
-nav_order: 99
----
-
-# Translations
-
-This documentation is translated by the community via [Crowdin](https://crowdin.com/project/meshtastic-android). Translations appear here automatically as volunteers contribute them.
-
-## Available Languages
-
-{% assign any_locale_exists = false %}
-{% for locale in site.data.locales %}
-{% assign locale_code = locale[0] %}
-{% assign locale_info = locale[1] %}
-{% assign locale_prefix = locale_code | append: "/" %}
-{% assign has_content = false %}
-{% for p in site.pages %}
- {% assign page_path_check = p.path | slice: 0, locale_prefix.size %}
- {% if page_path_check == locale_prefix %}
- {% assign has_content = true %}
- {% assign any_locale_exists = true %}
- {% break %}
- {% endif %}
-{% endfor %}
-
-{% if has_content %}
-- [{{ locale_info.name }}]({{ locale_code }}/) ({{ locale_code }})
-{% endif %}
-{% endfor %}
-
-{% unless any_locale_exists %}
-> No translations available yet. Want to help? [Join our Crowdin project β](https://crowdin.com/project/meshtastic-android)
-{% endunless %}
-
----
-
-## Contributing Translations
-
-1. Visit [Crowdin](https://crowdin.com/project/meshtastic-android)
-2. Select a language
-3. Translate the User Guide documentation files
-4. Translations are automatically synced to this site via PR
-
-Translation coverage and quality are tracked per-language. Pages without full translation show the English original for untranslated sections.
diff --git a/docs/en/user/connections.md b/docs/en/user/connections.md
index 0f69adb81b..ca17968d04 100644
--- a/docs/en/user/connections.md
+++ b/docs/en/user/connections.md
@@ -1,5 +1,6 @@
---
title: Connections
+parent: User Guide
nav_order: 2
last_updated: 2026-05-13
description: Connect your phone or desktop to a Meshtastic radio via Bluetooth, USB, or TCP/IP.
diff --git a/docs/en/user/desktop.md b/docs/en/user/desktop.md
index 8921fcb3f3..e2a369a9b6 100644
--- a/docs/en/user/desktop.md
+++ b/docs/en/user/desktop.md
@@ -1,5 +1,6 @@
---
title: Desktop App
+parent: User Guide
nav_order: 14
last_updated: 2026-05-13
description: Install and use the Meshtastic Desktop app on Linux, macOS, and Windows β connections, feature parity, and keyboard shortcuts.
diff --git a/docs/en/user/discovery.md b/docs/en/user/discovery.md
index 7a0fba364a..3ce9078d6a 100644
--- a/docs/en/user/discovery.md
+++ b/docs/en/user/discovery.md
@@ -1,5 +1,6 @@
---
title: Discovery
+parent: User Guide
nav_order: 12
last_updated: 2026-05-13
description: Explore your mesh network β traceroute paths, neighbor maps, and node discovery tools.
diff --git a/docs/en/user/firmware.md b/docs/en/user/firmware.md
index 0b0697ca45..c58788c87f 100644
--- a/docs/en/user/firmware.md
+++ b/docs/en/user/firmware.md
@@ -1,5 +1,6 @@
---
title: Firmware Updates
+parent: User Guide
nav_order: 13
last_updated: 2026-05-13
description: Update your radio firmware over Bluetooth β OTA process, version channels, pre-flight checks, and recovery.
diff --git a/docs/en/user/map-and-waypoints.md b/docs/en/user/map-and-waypoints.md
index 7f9e8f1dcd..0bb677ac8c 100644
--- a/docs/en/user/map-and-waypoints.md
+++ b/docs/en/user/map-and-waypoints.md
@@ -1,5 +1,6 @@
---
title: Map & Waypoints
+parent: User Guide
nav_order: 6
last_updated: 2026-05-13
description: View node positions on the map, create and share waypoints, and manage position sharing and privacy.
diff --git a/docs/en/user/messages-and-channels.md b/docs/en/user/messages-and-channels.md
index 0f8ed31755..3276987a18 100644
--- a/docs/en/user/messages-and-channels.md
+++ b/docs/en/user/messages-and-channels.md
@@ -1,5 +1,6 @@
---
title: Messages & Channels
+parent: User Guide
nav_order: 3
last_updated: 2026-05-13
description: Send and receive messages, manage channels, configure encryption, and use quick chat, reactions, and message actions.
diff --git a/docs/en/user/mqtt.md b/docs/en/user/mqtt.md
index 94c4c9db1e..5befabe8f2 100644
--- a/docs/en/user/mqtt.md
+++ b/docs/en/user/mqtt.md
@@ -1,5 +1,6 @@
---
title: MQTT
+parent: User Guide
nav_order: 11
last_updated: 2026-05-13
description: Bridge your mesh to the internet β MQTT broker setup, encryption layers, and map reporting.
diff --git a/docs/en/user/node-metrics.md b/docs/en/user/node-metrics.md
index e36b7cf386..eff885d687 100644
--- a/docs/en/user/node-metrics.md
+++ b/docs/en/user/node-metrics.md
@@ -1,5 +1,6 @@
---
title: Node Metrics
+parent: User Guide
nav_order: 5
last_updated: 2026-05-13
description: Telemetry dashboards for each mesh node β device health, environment sensors, signal quality, power, traceroute, and position history.
diff --git a/docs/en/user/nodes.md b/docs/en/user/nodes.md
index ec5f2ebd9b..07f82c0fd3 100644
--- a/docs/en/user/nodes.md
+++ b/docs/en/user/nodes.md
@@ -1,5 +1,6 @@
---
title: Nodes
+parent: User Guide
nav_order: 4
last_updated: 2026-05-13
description: Browse, filter, and sort mesh nodes β view details, signal quality, roles, and quick actions.
diff --git a/docs/en/user/onboarding.md b/docs/en/user/onboarding.md
index 11e64d42f1..07e033d78d 100644
--- a/docs/en/user/onboarding.md
+++ b/docs/en/user/onboarding.md
@@ -1,5 +1,6 @@
---
title: Getting Started
+parent: User Guide
nav_order: 1
last_updated: 2026-05-13
description: First-launch setup β permissions, onboarding flow, and next steps after connecting your radio.
diff --git a/docs/en/user/settings-module-admin.md b/docs/en/user/settings-module-admin.md
index 5cd31e7a75..f00f6cb899 100644
--- a/docs/en/user/settings-module-admin.md
+++ b/docs/en/user/settings-module-admin.md
@@ -1,5 +1,6 @@
---
title: Settings β Modules & Admin
+parent: User Guide
nav_order: 8
last_updated: 2026-05-13
description: Configure optional feature modules (MQTT, telemetry, canned messages, TAK, and more) and perform device administration.
diff --git a/docs/en/user/settings-radio-user.md b/docs/en/user/settings-radio-user.md
index f2bd9e2d8c..8edac752b4 100644
--- a/docs/en/user/settings-radio-user.md
+++ b/docs/en/user/settings-radio-user.md
@@ -1,5 +1,6 @@
---
title: Settings β Radio & User
+parent: User Guide
nav_order: 7
last_updated: 2026-05-13
description: Configure your radio hardware, LoRa presets, user profile, position sharing, power management, and security.
diff --git a/docs/en/user/signal-meter.md b/docs/en/user/signal-meter.md
index ce2d0a66d9..ba4fe5c01c 100644
--- a/docs/en/user/signal-meter.md
+++ b/docs/en/user/signal-meter.md
@@ -1,5 +1,6 @@
---
title: How the Meshtastic Signal Meter Works
+parent: User Guide
nav_order: 15
last_updated: 2026-05-13
description: How the signal meter calculates quality from RSSI and SNR β LoRa spread spectrum, presets, and what the bars really mean.
diff --git a/docs/en/user/tak.md b/docs/en/user/tak.md
index df6e8b827c..468fc8609b 100644
--- a/docs/en/user/tak.md
+++ b/docs/en/user/tak.md
@@ -1,5 +1,6 @@
---
title: TAK Integration
+parent: User Guide
nav_order: 10
last_updated: 2026-05-13
description: Interoperate with ATAK and WinTAK β CoT position sharing, TAK roles, and plugin setup.
diff --git a/docs/en/user/telemetry-and-sensors.md b/docs/en/user/telemetry-and-sensors.md
index 0ce596f0f5..c00920009e 100644
--- a/docs/en/user/telemetry-and-sensors.md
+++ b/docs/en/user/telemetry-and-sensors.md
@@ -1,5 +1,6 @@
---
title: Telemetry & Sensors
+parent: User Guide
nav_order: 9
last_updated: 2026-05-13
description: Sensor data on the mesh β supported environment, air quality, and power sensors, plus configuration and viewing guides.
Served by rngit 1.4.2 - Generated in 0.54s